package com.sise.recomder;

import com.sise.bean.PurchaseRecordBean;
import com.sise.entity.ProductInfo;
import com.sise.entity.User;
import com.sise.mapper.ProductInfoMapper;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.TreeSet;

/**
 * @author zj
 */
@Service
public class PurchaseRecomder {

    @Resource
    private PublicUse publicUse;

    @Resource
    private ProductInfoMapper productInfoMapper;

    //通过计算余弦相似度并取TopN, 返回为uid的用户生成的5个推荐菜品
    public List<ProductInfo> recommend(String open_id) {
        List<PurchaseRecordBean> purchaseRecordBeanList;                                   //其他用户收藏的菜品列表

        List<User> userList = publicUse.getUserList();
        List<ProductInfo> productInfoList = publicUse.getProductInfoList();
        int[][] curMatrix = new int[productInfoList.size() + 5][productInfoList.size() + 5];   //当前矩阵
        int[][] comMatrix = new int[productInfoList.size() + 5][productInfoList.size() + 5];   //共现矩阵
        int[] N = new int[productInfoList.size() + 5];                                       //喜欢每个物品的人数

        for (User user : userList) {
            if (user.getOpenId().equals(open_id)) continue;                                 //当前用户则跳过

            purchaseRecordBeanList = publicUse.queryOpenIdPurchaseList(user.getOpenId());

            for (int i = 0; i < productInfoList.size(); i++)
                for (int j = 0; j < productInfoList.size(); j++)
                    curMatrix[i][j] = 0;    //清空矩阵

            for (int i = 0; i < purchaseRecordBeanList.size(); i++) {
                int pid1 = purchaseRecordBeanList.get(i).getProductId();
                ++N[pid1];
                for (int j = i + 1; j < purchaseRecordBeanList.size(); j++) {
                    int pid2 = purchaseRecordBeanList.get(j).getProductId();
                    ++curMatrix[pid1][pid2];
                    ++curMatrix[pid2][pid1];    //两两加一
                }
            }

            //累加所有矩阵, 得到共现矩阵
            for (int i = 0; i < productInfoList.size(); i++) {
                for (ProductInfo productInfo : productInfoList) {
                    int pid1 = productInfoList.get(i).getProductId(), pid2 = productInfo.getProductId();
                    comMatrix[pid1][pid2] += curMatrix[pid1][pid2];
                    comMatrix[pid1][pid2] += curMatrix[pid1][pid2];
                }
            }
        }

        TreeSet<ProductInfo> preList = publicUse.preprocessingList();

        purchaseRecordBeanList = publicUse.queryOpenIdPurchaseList(open_id);

        boolean[] used = new boolean[productInfoList.size() + 5];  //判重数组
        for (PurchaseRecordBean purchaseRecordBean : purchaseRecordBeanList) {
            int Nij;                                                  //既喜欢i又喜欢j的人数
            double Wij;                                               //相似度
            ProductInfo tmp;                                          //当前的菜品

            int i = purchaseRecordBean.getProductId();
            for (ProductInfo productInfo : productInfoList) {
                if (purchaseRecordBean.getProductId().equals(productInfo.getProductId())) continue;
                int j = productInfo.getProductId();

                Nij = comMatrix[i][j];
                Wij = (double) Nij / Math.sqrt(N[i] * N[j]);             //计算余弦相似度

                tmp = productInfoMapper.selectById(productInfo.getProductId());
                tmp.setSimilarity(Wij);

                if (used[tmp.getProductId()]) continue;
                preList.add(tmp);
                used[tmp.getProductId()] = true;
            }
        }
        return publicUse.generateRecommendationResults(preList);
    }


}
